﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Gmantis.Controls.Chart
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    public class ShapeStyle
    {
        // Fields
        private DoubleCollection _dashArray;
        private Brush _fill;
        private Brush _stroke;
        private double _thickness;
        private Transform _transform;
        internal bool DarkOutline;
        internal Brush FillAuto;
        internal Brush StrokeAuto;

        // Events
        internal event EventHandler Changed;

        // Methods
        public ShapeStyle()
        {
            this.DarkOutline = true;
            this._thickness = 2.0;
        }

        internal ShapeStyle(Brush fill, Brush stroke, double thickness, DoubleCollection dashes)
        {
            this.DarkOutline = true;
            this._thickness = 2.0;
            this.Fill = fill;
            this.Stroke = stroke;
            this.StrokeThickness = thickness;
            this.StrokeDashArray = dashes;
        }

        internal void Apply(Shape sh)
        {
            this.Apply(null, sh, new Point(double.NaN, double.NaN), Extensions.EmptyRect, double.NaN, true);
        }

        internal void Apply(UIElement parent, Shape sh)
        {
            this.Apply(parent, sh, new Point(double.NaN, double.NaN), Extensions.EmptyRect, double.NaN, true);
        }

        internal void Apply(UIElement parent, Shape sh, Point center, Rect bounds, double radius)
        {
            this.Apply(parent, sh, center, bounds, radius, true);
        }

        internal void Apply(UIElement parent, Shape sh, Point center, Rect bounds, double radius, bool fill)
        {
            if ((sh.Fill == null) && fill)
            {
                Brush brush = this.Fill;
                RadialGradientBrush brush2 = this.Fill as RadialGradientBrush;
                if (((brush2 != null) && (parent != null)) && (!double.IsNaN(center.X) && !double.IsNaN(center.Y)))
                {
                    GradientStopCollection gradientStopCollection = new GradientStopCollection();
                    for (int i = 0; i < brush2.GradientStops.Count; i++)
                    {
                        GradientStop stop = new GradientStop
                        {
                            Color = brush2.GradientStops[i].Color,
                            Offset = brush2.GradientStops[i].Offset
                        };
                        gradientStopCollection.Add(stop);
                    }
                    RadialGradientBrush brush3 = new RadialGradientBrush(gradientStopCollection);
                    if (!bounds.IsEmptyRect())
                    {
                        double num2 = (Canvas.GetLeft(parent) + Canvas.GetLeft(sh)) + bounds.X;
                        double num3 = (Canvas.GetTop(parent) + Canvas.GetTop(sh)) + bounds.Y;
                        brush3.GradientOrigin = brush3.Center = new Point((center.X - num2) / bounds.Width, (center.Y - num3) / bounds.Height);
                        if (!double.IsNaN(radius) && (radius > 0.0))
                        {
                            if (bounds.Width > 1.0)
                            {
                                brush3.RadiusX = radius / bounds.Width;
                            }
                            if (bounds.Height > 1.0)
                            {
                                brush3.RadiusY = radius / bounds.Height;
                            }
                        }
                    }
                    brush = brush3;
                }
                sh.Fill = brush;
            }
            if (sh.Stroke == null)
            {
                UIElement tag = parent;
                if (!(parent is Lines))
                {
                    tag = sh.Tag as UIElement;
                }
                if (((tag is Lines) && !(tag is Area)) && (this.Stroke == this.StrokeAuto))
                {
                    if (((Lines)tag).IsFilled)
                    {
                        sh.Stroke = this.Stroke;
                    }
                    else
                    {
                        sh.Stroke = this.Fill;
                    }
                }
                else
                {
                    sh.Stroke = this.Stroke;
                }
            }
            if (this.StrokeThickness != 0.0)
            {
                sh.StrokeThickness = this.StrokeThickness;
            }
            if (this.StrokeDashArray != null)
            {
                DoubleCollection strokeDashArray = sh.StrokeDashArray;
                if (strokeDashArray == null)
                {
                    strokeDashArray = new DoubleCollection();
                    sh.StrokeDashArray = strokeDashArray;
                }
                else
                {
                    strokeDashArray.Clear();
                }
                int count = this.StrokeDashArray.Count;
                for (int j = 0; j < count; j++)
                {
                    strokeDashArray.Add(this.StrokeDashArray[j]);
                }
            }
            if (this.RenderTransform != null)
            {
                sh.RenderTransform = this.RenderTransform;
            }
        }

        internal bool CanConvertToString()
        {
            if ((this.Stroke != null) && !(this.Stroke is SolidColorBrush))
            {
                return false;
            }
            if (this.Fill != null)
            {
                return (this.Fill is SolidColorBrush);
            }
            return true;
        }

        internal string ConvertToString()
        {
            ConverterHelper helper = new ConverterHelper();
            if (this.Stroke is SolidColorBrush)
            {
                helper.Add("Stroke", this.Stroke);
            }
            if (this.Fill is SolidColorBrush)
            {
                helper.Add("Fill", this.Fill);
            }
            if (this.StrokeThickness != 1.0)
            {
                helper.Add("StrokeThickness", this.StrokeThickness);
            }
            return helper.ConvertToString();
        }

        private void FireChanged(object sender, EventArgs e)
        {
            if (this.Changed != null)
            {
                this.Changed(sender, e);
            }
        }

        internal static ShapeStyle ParseString(string s)
        {
            ShapeStyle style = null;
            ConverterHelper helper = ConverterHelper.ParseString(s);
            if (helper != null)
            {
                style = new ShapeStyle();
                if (helper.ContainsKey("StrokeThickness"))
                {
                    style.StrokeThickness = double.Parse(helper["StrokeThickness"].ToString(), CultureInfo.InvariantCulture);
                }
            }
            return style;
        }

        // Properties
        public Brush Fill
        {
            get
            {
                return this._fill;
            }
            set
            {
                this._fill = value;
                this.FireChanged(this, EventArgs.Empty);
            }
        }

        public Transform RenderTransform
        {
            get
            {
                return this._transform;
            }
            set
            {
                this._transform = value;
                this.FireChanged(this, EventArgs.Empty);
            }
        }

        public Brush Stroke
        {
            get
            {
                return this._stroke;
            }
            set
            {
                this._stroke = value;
                this.FireChanged(this, EventArgs.Empty);
            }
        }

        public DoubleCollection StrokeDashArray
        {
            get
            {
                return this._dashArray;
            }
            set
            {
                this._dashArray = value;
                this.FireChanged(this, EventArgs.Empty);
            }
        }

        public double StrokeThickness
        {
            get
            {
                return this._thickness;
            }
            set
            {
                this._thickness = value;
                this.FireChanged(this, EventArgs.Empty);
            }
        }
    }
}
